package com.cardone.common.router.support;

import java.util.Collection;
import java.util.Map;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.util.CollectionUtils;

import com.cardone.common.cache.Caches;
import com.cardone.common.template.util.TemplateUtils;

/**
 * 路由键名
 *
 * @author yaohaitao
 */
@Getter
@Setter
@Accessors(chain = true)
public class RouterKeyDefaultSupport implements RouterKeySupport {
	/**
	 * 默认路由键名配置
	 */
	private RouterKeyConfig defaultRouterKeyConfig;

	/**
	 * 路由键名配置
	 */
	private Map<String, RouterKeyConfig> routerKeyConfigs;

	@Override
	public String readKey(final String value) {
		return this.readKeyByGroupId(null, value, null);
	}

	@Override
	public String readKey(final String value, final Object model) {
		return this.readKeyByGroupId(null, value, model);
	}

	@Override
	@Cacheable(value = RouterKeySupport.BEAN_ID, key = Caches.KEY_3)
	public String readKeyByGroupId(final String groupId, final String value, final Object model) {
		String routerKey = null;

		do {
			// 没有传入值或没有配置路由信息时，直接返回默认键名
			if (StringUtils.isBlank(value) || CollectionUtils.isEmpty(this.routerKeyConfigs)) {
				routerKey = StringUtils.defaultIfBlank(this.defaultRouterKeyConfig.getTargetKey(), this.defaultRouterKeyConfig.getDefaultKey());
			}

			if (StringUtils.isNotBlank(routerKey)) {
				break;
			}

			// 有对应的组时
			if (this.routerKeyConfigs.containsKey(groupId)) {
				routerKey = this.readKeyByRouterKeyConfig(this.routerKeyConfigs.get(groupId), value, model);
			} else {
				routerKey = this.readKeyByRouterKeyConfigs(this.routerKeyConfigs.values(), value, model);
			}
		} while (false);

		if (StringUtils.isBlank(routerKey)) {
			routerKey = StringUtils.defaultIfBlank(this.defaultRouterKeyConfig.getTargetKey(), this.defaultRouterKeyConfig.getDefaultKey());
		}

		return routerKey;
	}

	private String readKeyByRouterKeyConfig(final RouterKeyConfig routerKeyConfig, final Object model) {
		String routerKey = null;

		if (StringUtils.isNotBlank(routerKeyConfig.getExpression())) {
			routerKey = TemplateUtils.processString(routerKeyConfig.getExpression(), model);
		}

		if (StringUtils.isNotBlank(routerKey)) {
			return StringUtils.trim(routerKey);
		}

		return StringUtils.defaultIfBlank(routerKeyConfig.getTargetKey(), routerKeyConfig.getDefaultKey());
	}

	private String readKeyByRouterKeyConfig(final RouterKeyConfig routerKeyConfig, final String value, final Object model) {
		String routerKey = null;

		if (StringUtils.endsWith(value, routerKeyConfig.getSuffix()) || StringUtils.contains(value, routerKeyConfig.getContain())) {
			return this.readKeyByRouterKeyConfig(routerKeyConfig, model);
		}

		if (StringUtils.isNotBlank(routerKeyConfig.getPrefix()) && !StringUtils.startsWith(value, routerKeyConfig.getPrefix())) {
			return null;
		}

		routerKey = this.readKeyByRouterKeyConfigs(routerKeyConfig.getChilds(), value, model);

		if (StringUtils.isNotBlank(routerKey)) {
			return routerKey;
		}

		return this.readKeyByRouterKeyConfig(routerKeyConfig, model);
	}

	private String readKeyByRouterKeyConfigs(final Collection<RouterKeyConfig> routerKeyConfigs, final String value, final Object model) {
		if (CollectionUtils.isEmpty(routerKeyConfigs)) {
			return null;
		}

		for (final RouterKeyConfig routerKeyConfig : routerKeyConfigs) {
			final String routerKey = this.readKeyByRouterKeyConfig(routerKeyConfig, value, model);

			if (StringUtils.isNotBlank(routerKey)) {
				return routerKey;
			}
		}

		return null;
	}
}